package cn.heyige.backend.service.impl;

import cn.heyige.backend.dto.*;
import cn.heyige.backend.entity.DivinationRecordDO;
import cn.heyige.backend.mapper.DivinationRecordMapper;
import cn.heyige.backend.service.DivinationRecordService;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 占卜记录管理服务实现类 - 精简版
 *
 * 专注于核心占卜记录管理功能，提高系统性能和可维护性
 * 增强数据验证和错误处理
 *
 * @author CodeBuddy
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class DivinationRecordServiceImpl implements DivinationRecordService {

    private final DivinationRecordMapper recordMapper;
    
    private static final int DEFAULT_PAGE_SIZE = 20;
    private static final int MAX_PAGE_SIZE = 50;
    private static final int EXPERIENCE_GAINED = 10;

    @Override
    @Transactional
    public SaveDivinationRecordResponse saveDivinationRecord(Integer userId, SaveDivinationRecordRequest request) {
        try {
            // 参数校验
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            if (request == null) {
                throw new IllegalArgumentException("保存请求不能为空");
            }

            if (!StringUtils.hasText(request.getQuestion())) {
                throw new IllegalArgumentException("占卜问题不能为空");
            }

            if (!StringUtils.hasText(request.getHexagram())) {
                throw new IllegalArgumentException("卦象不能为空");
            }

            // 构建占卜记录
            DivinationRecordDO record = DivinationRecordDO.builder()
                    .userId(userId)
                    .hexagramName(request.getHexagram())
                    .hexagramCode(request.getHexagram())
                    .question(request.getQuestion())
                    .inputData(JSONUtil.toJsonStr(request.getInputData()))
                    .hexagramData(JSONUtil.toJsonStr(request.getHexagramData()))
                    .build();

            // 保存记录
            recordMapper.insert(record);

            // 检查成就
            List<SaveDivinationRecordResponse.Achievement> achievements = checkAchievements(userId);

            return SaveDivinationRecordResponse.builder()
                    .id(record.getId())
                    .userId(userId)
                    .createdAt(record.getCreateTime())
                    .experienceGained(EXPERIENCE_GAINED)
                    .achievements(achievements)
                    .build();

        } catch (Exception e) {
            log.error("保存占卜记录失败: {}", e.getMessage());
            throw new RuntimeException("保存占卜记录失败: " + e.getMessage());
        }
    }

    @Override
    public DivinationHistoryResponse getDivinationHistory(Integer userId, Integer page, Integer size,
                                                          LocalDate startDate, LocalDate endDate, String sort) {
        try {
            // 参数校验
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            // 创建分页对象
            Page<DivinationRecordDO> pageObj = createPage(page, size);

            // 执行查询
            IPage<DivinationRecordDO> recordPage = executeQuery(pageObj, userId, startDate, endDate);

            // 转换为响应格式
            List<DivinationHistoryResponse.DivinationRecord> records = recordPage.getRecords().stream()
                    .map(this::convertToHistoryRecord)
                    .collect(Collectors.toList());

            // 构建分页信息
            DivinationHistoryResponse.PaginationInfo pagination = DivinationHistoryResponse.PaginationInfo.builder()
                    .page((int) recordPage.getCurrent())
                    .size((int) recordPage.getSize())
                    .total(recordPage.getTotal())
                    .totalPages((int) recordPage.getPages())
                    .hasNext(recordPage.getCurrent() < recordPage.getPages())
                    .hasPrevious(recordPage.getCurrent() > 1)
                    .build();

            // 构建统计摘要
            DivinationHistoryResponse.SummaryInfo summary = buildSummaryInfo(userId);

            return DivinationHistoryResponse.builder()
                    .pagination(pagination)
                    .records(records)
                    .summary(summary)
                    .build();

        } catch (Exception e) {
            log.error("获取占卜历史记录失败: {}", e.getMessage());
            throw new RuntimeException("获取占卜历史记录失败: " + e.getMessage());
        }
    }

    @Override
    public DivinationRecordDetailResponse getDivinationRecordDetail(Integer userId, Integer recordId) {
        try {
            // 参数校验
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            if (recordId == null) {
                throw new IllegalArgumentException("记录ID不能为空");
            }

            DivinationRecordDO record = recordMapper.findByUserIdAndRecordId(userId, recordId);
            if (record == null) {
                throw new RuntimeException("记录不存在");
            }

            // 增加查看次数
            record.setViewCount(record.getViewCount() + 1);
            recordMapper.updateById(record);

            return convertToDetailResponse(record);

        } catch (Exception e) {
            log.error("获取占卜记录详情失败: {}", e.getMessage());
            throw new RuntimeException("获取占卜记录详情失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public FavoriteOperationResponse toggleFavorite(Integer userId, FavoriteRequest request) {
        try {
            // 参数校验
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            if (request == null) {
                throw new IllegalArgumentException("收藏请求不能为空");
            }

            if (request.getRecordId() == null) {
                throw new IllegalArgumentException("记录ID不能为空");
            }

            if (!StringUtils.hasText(request.getAction())) {
                throw new IllegalArgumentException("操作类型不能为空");
            }

            DivinationRecordDO record = recordMapper.findByUserIdAndRecordId(userId, request.getRecordId());
            if (record == null) {
                throw new RuntimeException("记录不存在");
            }

            boolean isFavorite;
            if ("ADD".equals(request.getAction())) {
                record.setIsFavorite(true);
                record.setFavoriteTime(LocalDateTime.now());
                isFavorite = true;
            } else if ("REMOVE".equals(request.getAction())) {
                record.setIsFavorite(false);
                record.setFavoriteTime(null);
                isFavorite = false;
            } else {
                throw new RuntimeException("无效的操作类型");
            }

            recordMapper.updateById(record);

            // 获取用户总收藏数
            long favoriteCount = recordMapper.countByUserIdAndIsFavoriteTrue(userId);

            return FavoriteOperationResponse.builder()
                    .recordId(request.getRecordId())
                    .isFavorite(isFavorite)
                    .favoriteCount((int) favoriteCount)
                    .operatedAt(LocalDateTime.now())
                    .build();

        } catch (Exception e) {
            log.error("收藏操作失败: {}", e.getMessage());
            throw new RuntimeException("收藏操作失败: " + e.getMessage());
        }
    }

    @Override
    public FavoriteListResponse getFavoriteList(Integer userId, Integer page, Integer size) {
        try {
            // 参数校验
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            Page<DivinationRecordDO> pageObj = new Page<>(
                    page != null ? page : 1,
                    size != null ? Math.min(size, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE
            );

            IPage<DivinationRecordDO> favoritePage = recordMapper.findByUserIdAndIsFavoriteTrueOrderByFavoritedAtDesc(pageObj, userId);

            List<FavoriteListResponse.FavoriteRecord> records = favoritePage.getRecords().stream()
                    .map(this::convertToFavoriteRecord)
                    .collect(Collectors.toList());

            DivinationHistoryResponse.PaginationInfo pagination = DivinationHistoryResponse.PaginationInfo.builder()
                    .page((int) favoritePage.getCurrent())
                    .size((int) favoritePage.getSize())
                    .total(favoritePage.getTotal())
                    .totalPages((int) favoritePage.getPages())
                    .hasNext(favoritePage.getCurrent() < favoritePage.getPages())
                    .hasPrevious(favoritePage.getCurrent() > 1)
                    .build();

            return FavoriteListResponse.builder()
                    .pagination(pagination)
                    .records(records)
                    .build();

        } catch (Exception e) {
            log.error("获取收藏列表失败: {}", e.getMessage());
            throw new RuntimeException("获取收藏列表失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public boolean deleteDivinationRecord(Integer userId, Integer recordId) {
        try {
            // 参数校验
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }

            if (recordId == null) {
                throw new IllegalArgumentException("记录ID不能为空");
            }

            long deletedCount = recordMapper.deleteByUserIdAndRecordId(userId, recordId);
            return deletedCount > 0;
        } catch (Exception e) {
            log.error("删除占卜记录失败: {}", e.getMessage());
            return false;
        }
    }


    private Page<DivinationRecordDO> createPage(Integer page, Integer size) {
        long pageNumber = page != null ? page : 1;
        long pageSize = size != null ? Math.min(size, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;
        return new Page<>(pageNumber, pageSize);
    }

    private IPage<DivinationRecordDO> executeQuery(Page<DivinationRecordDO> pageObj, Integer userId, LocalDate startDate,LocalDate endDate) {

        LocalDateTime startDateTime = startDate != null ? startDate.atStartOfDay() : null;
        LocalDateTime endDateTime = endDate != null ? endDate.atTime(23, 59, 59) : null;

        // 根据参数选择查询方法
        if(startDateTime != null && endDateTime != null) {
            return recordMapper.findByUserIdAndCreatedAtBetweenOrderByCreatedAtDesc(
                    pageObj, userId, startDateTime, endDateTime);
        } else {
            return recordMapper.findByUserIdOrderByCreatedAtDesc(pageObj, userId);
        }
    }

    private DivinationHistoryResponse.DivinationRecord convertToHistoryRecord(DivinationRecordDO record) {

        return DivinationHistoryResponse.DivinationRecord.builder()
                .id(record.getId())
                .question(record.getQuestion())
                .hexagram(buildHexagramInfo(record.getHexagramCode(), record.getHexagramName()))
                .isFavorite(record.getIsFavorite())
                .hasAiInterpretation(record.getAiInterpretation() != null)
                .feedbackRating(record.getFeedbackRating())
                .createdAt(record.getCreateTime())
                .build();
    }

    private DivinationRecordDetailResponse convertToDetailResponse(DivinationRecordDO record) {
        return DivinationRecordDetailResponse.builder()
                .id(record.getId())
                .question(record.getQuestion())
                .inputData(record.getInputData() != null ? JSONUtil.parseObj(record.getInputData()) : new HashMap<>())
                .hexagram(buildHexagramDetail(record.getHexagramCode(), record.getHexagramName()))
                .aiInterpretation(buildAiInterpretationInfo(record))
                .isFavorite(record.getIsFavorite())
                .feedbackRating(record.getFeedbackRating())
                .feedbackComment(record.getFeedbackComment())
                .shareCount(record.getShareCount())
                .viewCount(record.getViewCount())
                .createdAt(record.getCreateTime())
                .updatedAt(record.getUpdateTime())
                .build();
    }

    private FavoriteListResponse.FavoriteRecord convertToFavoriteRecord(DivinationRecordDO record) {
        return FavoriteListResponse.FavoriteRecord.builder()
                .id(record.getId())
                .question(record.getQuestion())
                .hexagram(buildFavoriteHexagramInfo(record.getHexagramCode(), record.getHexagramName()))
                .createdAt(record.getCreateTime())
                .favoritedAt(record.getFavoriteTime())
                .build();
    }

    private HexagramInfo buildFavoriteHexagramInfo(String hexagramCode, String hexagramName) {
        return HexagramInfo.builder()
                .code(hexagramCode)
                .name(hexagramName)
                .upperSymbol("☲")
                .lowerSymbol("☰")
                .build();
    }

    private DivinationHistoryResponse.DivinationRecord.HexagramInfo buildHexagramInfo(String hexagramCode, String hexagramName) {
        return DivinationHistoryResponse.DivinationRecord.HexagramInfo.builder()
                .code(hexagramCode)
                .name(hexagramName)
                .upperSymbol("☲")
                .lowerSymbol("☰")
                .build();
    }

    private DivinationRecordDetailResponse.HexagramDetail buildHexagramDetail(String hexagramCode, String hexagramName) {
        return DivinationRecordDetailResponse.HexagramDetail.builder()
                .id(1)
                .name(hexagramName)
                .code(hexagramCode)
                .upperTrigram(DivinationRecordDetailResponse.TrigramInfo.builder()
                        .name("离")
                        .symbol("☲")
                        .element("火")
                        .build())
                .lowerTrigram(DivinationRecordDetailResponse.TrigramInfo.builder()
                        .name("乾")
                        .symbol("☰")
                        .element("金")
                        .build())
                .hexagramText("卦辞内容")
                .build();
    }

    private DivinationRecordDetailResponse.AiInterpretationInfo buildAiInterpretationInfo(DivinationRecordDO record) {
        if (record.getAiInterpretation() == null) {
            return null;
        }

        return DivinationRecordDetailResponse.AiInterpretationInfo.builder()
                .summary(record.getAiInterpretation())
                .confidence(0.85)
                .generatedAt(record.getCreateTime())
                .build();
    }

    private DivinationHistoryResponse.SummaryInfo buildSummaryInfo(Integer userId) {
        // 获取统计数据
        long totalRecords = recordMapper.countByUserId(userId);
        long favoriteCount = recordMapper.countByUserIdAndIsFavoriteTrue(userId);
        Double averageRating = recordMapper.getAverageRatingByUserId(userId);

        return DivinationHistoryResponse.SummaryInfo.builder()
                .totalRecords(totalRecords)
                .favoriteCount((int) favoriteCount)
                .averageRating(averageRating != null ? averageRating : 0.0)
                .build();
    }

    private List<SaveDivinationRecordResponse.Achievement> checkAchievements(Integer userId) {
        List<SaveDivinationRecordResponse.Achievement> achievements = new ArrayList<>();
        // 检查占卜次数成就
        if (recordMapper.countByUserId(userId) == 10) {
            achievements.add(SaveDivinationRecordResponse.Achievement.builder()
                    .type("DIVINATION_COUNT")
                    .name("初步探索")
                    .description("完成第10次占卜")
                    .unlockedAt(LocalDateTime.now())
                    .build());
        }
        return achievements;
    }

}